#!/usr/bin/python
# -*- coding: utf-8 -*-

import os
import sys
import threading
import ConfigParser as cfg

from PyQt4 import QtCore, QtGui
import datetime

import plugin.config
import widgets

base_path = os.path.abspath(os.path.dirname(sys.argv[0]))

ADD_MOVIE_EVENT = QtCore.QEvent.User
class AddMovieEvent(QtCore.QEvent):
    def __init__(self, data):
        self.data = data
        QtCore.QEvent.__init__(self, ADD_MOVIE_EVENT)

class SearchThread(threading.Thread):
    def __init__(self, window, plugin, query, options):
        threading.Thread.__init__(self)
        self.window = window
        self.plugin = plugin
        self.query = query
        self.options = options
        
    def run(self):
        self.plugin.search(self.query, self.options)
        list = self.plugin.list()
        evt = AddMovieEvent((self.plugin, list))
        QtGui.QApplication.postEvent(self.window, evt)
        self.plugin.fetching = False
        if self.window.plugin == self.plugin:
            self.window.refineBtn.setEnabled(True)
        
""" Main widget, the frame. """
class MainWindow(QtGui.QWidget):
    
    def __init__(self, groupName): 
        QtGui.QWidget.__init__(self)
        
        self.setWindowTitle("Ratings")
        self.setWindowIcon(self.icon('film.png'))
        self.searchAll = False
        self.plugin = None
        self.group = None
        self.groupName = groupName
        self.inputDialog = None
        self.cfgPath = os.path.sep.join((base_path, 'res', 'settings.cfg'))
        
        self.pluginBoxCache = {}
        for k in plugins.groups.keys():
            self.pluginBoxCache[k] = None
        
        self._create_widgets()
        
        self.read_cfg()
        self.set_group(self.groupName)
        self.pluginBox.setFocus(QtCore.Qt.OtherFocusReason)
        self.update_title()        
    
    def update_title(self, qr=None):
        txt = "Ratings (%s)" % self.groupName
        if qr is None:
            qr = self.plugin.lastQuery
        if qr is not None and len(qr) != 0:
            txt = ' - '.join((txt, qr))
        self.setWindowTitle(txt)
    
    def read_cfg(self):
        try:
            file = open(self.cfgPath, 'rU')
            for line in file.readlines():
                line = line.lstrip()
                if not line.startswith('#'):
                    a = line.split('>')
                    grp = a[0].strip()
                    if grp.startswith('~') and not grp.startswith('~~'):
                        grp = grp[1:]
                        if self.groupName is None:
                            self.groupName = grp
                    plg = a[1].strip()
                    self.pluginBoxCache[grp] = plg
            file.close()
        except Exception, e:
            print "error reading config file",e
            
        if self.groupName is None:
            g = plugins.groups.keys()
            if len(g) == 0:
                raise Exception("no groups to search! check plugins/config.py")
            self.groupName = g[0]
    
    def write_cfg(self):
        try:
            file = open(self.cfgPath, 'w')
            date = datetime.datetime.now().strftime("%B %d %I:%M %p %Y")
            file.write("#Preferences generated on %s\n" % date)
            if self.groupName is not None and self.plugin is not None:
                self.pluginBoxCache[self.groupName] = self.plugin.name
            for k, v in self.pluginBoxCache.iteritems():
                k = k.replace('~', '~~')
                if k == self.groupName:
                    k = ''.join(('~', k))
                file.write("%s > %s\n" % (k, v))
            file.close()
        except Exception, e:
            print "error writing config file",e
    
    def cleanup(self):
        self.write_cfg()
        
    def icon(self, ref):
        return QtGui.QIcon(os.path.sep.join((base_path, 'res', ref)))
    
    def list_double_click(self, index):
        if index.isValid() and self.list.model().rowCount() != 0:
            url = self.list.model().arraydata[-1][1]
            if len(url) != 0:
                import webbrowser
                webbrowser.open(url)
    
    def customEvent(self, e):
        if e.type() == ADD_MOVIE_EVENT:
            plugin, mv = e.data
            if plugin == self.plugin:
                #if the plugin is the selected plugin, update the view
                if plugin.header != self.list.headers:
                    self.list.set_headers(plugin.header)
                    self.list.updateList()
                self.list.set_movie(mv)
                self.list.updateList()
        
    def query(self):
        if self.inputDialog is None:
            self.inputDialog = widgets.InputDialog(self)
        txt = self.plugin.lastQuery
        ok, groupName, query = self.inputDialog.query("Search", self.groupName, txt)
        if ok:
            self.set_group(groupName)
            if len(query) != 0:
                self._search(query)
                self.update_title(query)
    
    def refine(self):
        if self.inputDialog is None:
            self.inputDialog = widgets.InputDialog(self)
        ok, query = self.inputDialog.refine("Refine", self.plugin.lastQuery)
        if ok and len(query) != 0:
            self._search(query, True)
            self.update_title(query)
    
    def _search(self, str, single=False):
        self.list.clear()
        if single: 
            #if we are only fetching from the selected plugin
            plugin = self.plugin
            self._searchPlugin(plugin, str)
        else:
            for plugin in self.group:
                self._searchPlugin(plugin, str)
        
    def _searchPlugin(self, plugin, str):
        plugin.cache = []
        t = SearchThread(self, plugin, str, plugins.options)
        plugin.fetching = True
        self.refineBtn.setEnabled(False)
        t.start()
            
    def plugin_change(self, i):
        if i != -1:
            self.plugin = plugins.get(self.group, str(self.pluginBox.currentText()))
            d = [] if not self.plugin.display \
                   else widgets.List.to_data(self.plugin.list(), self.plugin.header)
            self.list.model().arraydata = d
            self.list.set_headers(self.plugin.header)
            self.list.updateList()
            self.refineBtn.setEnabled(not self.plugin.fetching)
            self.update_title()
            
    def set_plugin(self, pluginName):
        """ Selects the plugin by the given name in the current group. """
        i = self.pluginBox.findText(pluginName)
        if i != -1:
            self.pluginBox.setCurrentIndex(i)
                    
    def set_group(self, groupName):
        #first we store the plugin name of the current group
        if self.plugin is not None:
            self.pluginBoxCache[self.groupName] = self.plugin.name
        
        newGroup = plugins.group(groupName)
        if newGroup is not None and self.group != newGroup:
            self.groupName = groupName
            self.group = newGroup
            self.pluginBox.clear()
            for v in self.group:
                self.pluginBox.addItem(v.name)
            if self.pluginBoxCache[groupName] is not None:
                self.set_plugin(self.pluginBoxCache[groupName])
        self.update_title()
    
    def _icobutton(self, icon, tip, func):
        btn = QtGui.QToolButton(self)
        btn.setToolTip(tip)
        btn.setIcon(self.icon(icon))
        btn.setIconSize(QtCore.QSize(22, 22))
        btn.setAutoRaise(True)
        self.connect(btn, QtCore.SIGNAL("clicked()"), func)
        return btn
    
    def _create_widgets(self): 
        self.resize(320, 202)
        
        #top panel
        self.pluginLabel = QtGui.QLabel("Site:")
        self.pluginLabel.setMinimumHeight(21)
        
        self.pluginBox = QtGui.QComboBox(self)
        self.pluginBox.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents)
        self.pluginBox.setToolTip("The review site to search")
        self.connect(self.pluginBox, QtCore.SIGNAL("currentIndexChanged(int)"), 
                     self.plugin_change)
        self.pluginBox.setMinimumHeight(21)
        
        #TOOLBAR BUTTONS
        self.queryBtn = self._icobutton('btn_new.png', "Start a new search", 
                                   self.query)
        self.refineBtn = self._icobutton('btn_refine.png', 
                                    "Refine search for selected site", 
                                    self.refine)
        
        self.closeBtn = QtGui.QPushButton(self.tr("&Close"), self)
        self.connect(self.closeBtn, QtCore.SIGNAL("clicked()"), self.close)
        
        #list widget
        self.list = widgets.List(["Name", "Value"])
        self.list.setMinimumSize(self.width(), 70)
        self.connect(self.list, 
                     QtCore.SIGNAL('doubleClicked(QModelIndex)'),
                     self.list_double_click)
        
        topPanel = widgets.flow([self.pluginLabel, self.pluginBox,
                                 "stretch", self.queryBtn, self.refineBtn])
        botPanel = widgets.flow(["stretch", self.closeBtn, "stretch"])
                
        layout = QtGui.QVBoxLayout()
        layout.addWidget(topPanel)
        layout.addWidget(self.list)
        layout.addWidget(botPanel)
        self.setLayout(layout)
        
        w = QtGui.QApplication.desktop().width()
        h = QtGui.QApplication.desktop().height()
        self.move(w/2 - self.width()/2, 
                  h/2 - self.height()/2)
        
def main():
    app = QtGui.QApplication(sys.argv)
    
    groupName = None
    pluginName = None
    ignoreYear = False
    torrentFormat = False
    for i in range(len(sys.argv)):
        if len(sys.argv) > 1:
            if sys.argv[1].startswith("-"):
                x = sys.argv[1]
                sys.argv.remove(x)
                e = x[1:].lower()
                if e == "noyr":
                    ignoreYear = True
                elif e == "bt":
                    torrentFormat = True
                elif e.startswith("group"):
                    #e.g. -group=Games
                    groupName = x[7:]
                elif e.startswith("plugin"):
                    #e.g. -plugin=IMDB
                    pluginName = x[8:]
                else:
                    raise Exception("-%s is not an engine" % e)
    
    plugins.options["ignoreYear"] = ignoreYear
    plugins.options["torrentFormat"] = torrentFormat
    w = MainWindow(groupName)
    QtCore.QObject.connect(app, QtCore.SIGNAL('aboutToQuit()'), w.cleanup)
    
    w.show()
    
    #passed arguments
    if groupName is not None:
        w.set_group(groupName)
    if pluginName is not None:
        w.set_plugin(pluginName)
    
    #If no arg is specified, request query...
    if len(sys.argv) <= 1:
        w.query()
    else:
        w._search(sys.argv[1])
        
    sys.exit(app.exec_())
 
if __name__ == "__main__": 
    main()